package android.content.impl;

import android.content.SharedPreferences;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;

/**
 * @author slc
 * @date 2022/03/30 下午 5:16
 */
public class SharedPreferencesImpl implements SharedPreferences {
    private final Map<String, Object> dataMap = new ConcurrentHashMap<>();
    private final List<OnSharedPreferenceChangeListener> sharedPreferenceChangeListenerList = new ArrayList<>();

    public SharedPreferencesImpl() {

    }

    @Override
    public Map<String, ?> getAll() {
        return new ConcurrentHashMap<>(dataMap);
    }

    @Override
    public String getString(String key, String defValue) {
        return (String) dataMap.getOrDefault(key, defValue);
    }

    @Override
    public Set<String> getStringSet(String key, Set<String> defValues) {
        return (Set<String>) dataMap.getOrDefault(key, defValues);
    }

    @Override
    public int getInt(String key, int defValue) {
        return (int) dataMap.getOrDefault(key, defValue);
    }

    @Override
    public long getLong(String key, long defValue) {
        return (long) dataMap.getOrDefault(key, defValue);
    }

    @Override
    public float getFloat(String key, float defValue) {
        return (float) dataMap.getOrDefault(key, defValue);
    }

    @Override
    public boolean getBoolean(String key, boolean defValue) {
        return (boolean) dataMap.getOrDefault(key, defValue);
    }

    @Override
    public boolean contains(String key) {
        return dataMap.containsKey(key);
    }

    @Override
    public Editor edit() {
        return new EditorImpl(this);
    }

    @Override
    public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
        sharedPreferenceChangeListenerList.add(listener);
    }

    @Override
    public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
        sharedPreferenceChangeListenerList.remove(listener);
    }

    public static class EditorImpl implements Editor {

        private final Map<String, Object> tempDataMap = new ConcurrentHashMap<>();
        private final List<String> tempRemoveKeyList = new ArrayList<>();
        private boolean tempClear = false;
        private SharedPreferencesImpl sharedPreferences;

        public EditorImpl(SharedPreferencesImpl sharedPreferences) {
            this.sharedPreferences = sharedPreferences;
        }

        @Override
        public Editor putString(String key, String value) {
            tempDataMap.put(key, value);
            return this;
        }

        @Override
        public Editor putStringSet(String key, Set<String> values) {
            tempDataMap.put(key, values);
            return this;
        }

        @Override
        public Editor putInt(String key, int value) {
            tempDataMap.put(key, value);
            return this;
        }

        @Override
        public Editor putLong(String key, long value) {
            tempDataMap.put(key, value);
            return this;
        }

        @Override
        public Editor putFloat(String key, float value) {
            tempDataMap.put(key, value);
            return null;
        }

        @Override
        public Editor putBoolean(String key, boolean value) {
            tempDataMap.put(key, value);
            return this;
        }

        @Override
        public Editor put(String key, Object value) {
            tempDataMap.put(key, value);
            return this;
        }

        @Override
        public Editor remove(String key) {
            tempDataMap.remove(key);
            return this;
        }

        @Override
        public Editor clear() {
            this.tempClear = true;
            return this;
        }

        @Override
        public boolean commit() {
            checkReason();
            tempRemoveKeyList.forEach(new Consumer<String>() {
                @Override
                public void accept(String item) {
                    sharedPreferences.dataMap.remove(item);
                }
            });
            if (tempClear) {
                sharedPreferences.dataMap.clear();
            } else {
                sharedPreferences.dataMap.putAll(tempDataMap);
            }
            return true;
        }

        @Override
        public void apply() {
            commit();
        }

        /**
         * 检车合理性
         */
        private void checkReason() {
            if (tempClear && !tempDataMap.isEmpty()) {
                throw new RuntimeException("不用同时使用clear()和put*()方法");
            }
        }
    }
}
